package com.gxa.community.customer.service.cart.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gxa.community.core.pojo.bo.cart.CartGoodsInfoBo;
import com.gxa.community.core.pojo.bo.classification.GoodsInfoBo1;
import com.gxa.community.core.pojo.dto.cart.CartDTO;
import com.gxa.community.core.pojo.vo.cart.CartVO;
import com.gxa.community.core.pojo.vo.cart.GoodsVO;
import com.gxa.community.core.utils.R;
import com.gxa.community.customer.service.cart.CartService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
@Transactional(rollbackFor = Throwable.class)
public class CartServiceImpl implements CartService {
    public static final String CART_INFO = "cart:";
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;


    /**
     * 查询当前登录用户购物车信息
     * @param userId
     * @return
     */
    @Override
    public String queryCartInfo(Integer userId) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        //从redis中获取,购物车信息存放于redis中，提高效率  因为购物车的增删改频繁
        Object cartInfo = redisTemplate.opsForValue().get(CART_INFO + userId);
        if (StringUtils.isEmpty(cartInfo)){
            R result = R.error(600, "购物车空空如也，建议去逛逛！");
            return objectMapper.writeValueAsString(result);
        }else {

            CartDTO cartDTO = new CartDTO();
            //先将redis中用户购物车信息反序列化
            CartVO cartVO = objectMapper.readValue(cartInfo.toString(), CartVO.class);
            cartDTO.setUserId(cartVO.getUserId());
            cartDTO.setUpdateTime(cartVO.getUpdateTime());
            List<GoodsVO> goodsVOList = cartVO.getGoodsVOList();
            if (CollectionUtils.isEmpty(goodsVOList)){
                return objectMapper.writeValueAsString(R.error(600, "购物车空空如也，建议去逛逛！"));
            }
            //redis中存在该用户的购物车，需要对返回的商品数据进行包装，
            //TODO 需要返回商品的详细信息且是最新的，若用户添加的商品中有下架的，则显示失效
            String allgoods = (String) redisTemplate.opsForValue().get("allgoods");
            if (StringUtils.isEmpty(allgoods)){
                //TODO (远程调用)如果没有所有商品信息，则去发起远程调用，向缓存中存放
                String url = "http://kinggo.icu:8080/cart/getallgoods";
                allgoods = restTemplate.getForObject(url, String.class);
                redisTemplate.opsForValue().set("allgoods",allgoods);
            }
            List<GoodsInfoBo1> goodsInfoBo1List = objectMapper.readValue(allgoods,List.class);
            //todo 当对象中含有对象  需使用下列步骤进行反序列化
            List<GoodsInfoBo1> goodsInfoBo1List1 = objectMapper.convertValue(goodsInfoBo1List, new TypeReference<List<GoodsInfoBo1>>() {
                @Override
                public Type getType() {
                    return super.getType();
                }
            });
            //包装当前用户购物车商品信息
            List<CartGoodsInfoBo> cartGoodsInfoBoList = new ArrayList<>();
            for (GoodsVO goodsVO : goodsVOList) {
                for (GoodsInfoBo1 goodsInfoBo1 : goodsInfoBo1List1) {
                    if (goodsVO.getId()==goodsInfoBo1.getId()){
                        CartGoodsInfoBo cartGoodsInfoBo = new CartGoodsInfoBo();
                        cartGoodsInfoBo.setGoodsInfoBo1(goodsInfoBo1);
                        cartGoodsInfoBo.setQuantity(goodsVO.getQuantity());
                        cartGoodsInfoBo.setChecked(goodsVO.getChecked());
                        cartGoodsInfoBoList.add(cartGoodsInfoBo);
                    }
                }
            }
            cartDTO.setCartGoodsInfoBoList(cartGoodsInfoBoList);
            String result = objectMapper.writeValueAsString(cartDTO);
            return result;
        }
    }

    @Override
    public String addCart(Integer userId,Integer goodsId,Integer goodsQuantity) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        Object cartUserId = redisTemplate.opsForValue().get(CART_INFO + userId);
        if (StringUtils.isEmpty(cartUserId)){
            //当前用户没有购物车，为其直接创建
            CartVO cartVO = new CartVO();
            cartVO.setUserId(userId);
            List<GoodsVO> goodsVOList = new ArrayList<>();
            GoodsVO goodsVO = new GoodsVO();
            goodsVO.setId(goodsId);
            goodsVO.setQuantity(goodsQuantity);
            goodsVO.setChecked(1);
            log.info("{}",goodsVO);
            goodsVOList.add(goodsVO);
            cartVO.setGoodsVOList(goodsVOList);
            cartVO.setUpdateTime(System.currentTimeMillis());
            String s = objectMapper.writeValueAsString(cartVO);
            redisTemplate.opsForValue().set(CART_INFO+cartVO.getUserId(),s);
            return "success!";
        }else {
            //该用户已经存在购物车，需要跟新购物车信息
            CartVO cartVO = objectMapper.readValue(cartUserId.toString(), CartVO.class);
            List<GoodsVO> goodsVOList = cartVO.getGoodsVOList();
            Boolean flag = false;
            for (GoodsVO goodsVO : goodsVOList) {
                if (goodsVO.getId() == goodsId){
                    int i = goodsVO.getQuantity() + goodsQuantity;
                    goodsVO.setQuantity(i);
                    flag = true;//说明该商品用户之前已经添加到购物车，现在只更新数量
                }
            }
            if (!flag){
                //说明该用户的购物车并没有该商品
                GoodsVO goodsVO = new GoodsVO();
                goodsVO.setId(goodsId);
                goodsVO.setQuantity(goodsQuantity);
                goodsVO.setChecked(1);
                goodsVOList.add(goodsVO);
            }
            cartVO.setGoodsVOList(goodsVOList);
            cartVO.setUpdateTime(System.currentTimeMillis());
            String result = objectMapper.writeValueAsString(cartVO);
            //直接覆盖当前用户原购物车信息
            redisTemplate.opsForValue().set(CART_INFO+userId,result);
            return "success!";
        }
    }

    @Override
    public String addCartGoodsQuantityBy1(Integer userId, Integer goodsId) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        String cartUserId = (String) redisTemplate.opsForValue().get(CART_INFO + userId);
        CartVO cartVO = objectMapper.readValue(cartUserId, CartVO.class);
        List<GoodsVO> goodsVOList = cartVO.getGoodsVOList();
        for (GoodsVO goodsVO : goodsVOList) {
            if (goodsVO.getId() == goodsId){
                int i = goodsVO.getQuantity() + 1;
                goodsVO.setQuantity(i);
            }
        }
        cartVO.setGoodsVOList(goodsVOList);
        cartVO.setUpdateTime(System.currentTimeMillis());
        String s = objectMapper.writeValueAsString(cartVO);
        redisTemplate.opsForValue().set(CART_INFO+userId,s);
        return "success!";
    }

    @Override
    public String delCartGoodsQuantityBy1(Integer userId, Integer goodsId) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        String cartUserId = (String) redisTemplate.opsForValue().get(CART_INFO + userId);
        CartVO cartVO = objectMapper.readValue(cartUserId, CartVO.class);
        List<GoodsVO> goodsVOList = cartVO.getGoodsVOList();
        for (GoodsVO goodsVO : goodsVOList) {
            if (goodsVO.getId() == goodsId){
                int i = goodsVO.getQuantity() - 1;
                goodsVO.setQuantity(i);
            }
        }
        cartVO.setGoodsVOList(goodsVOList);
        cartVO.setUpdateTime(System.currentTimeMillis());
        String s = objectMapper.writeValueAsString(cartVO);
        redisTemplate.opsForValue().set(CART_INFO+userId,s);
        return "success!";
    }

    @Override
    public String delCartGoodsBatch(Integer userId,Integer... goodsIds) throws JsonProcessingException {
        Integer count = 0;
        ObjectMapper objectMapper = new ObjectMapper();
        String cartUserId = (String) redisTemplate.opsForValue().get(CART_INFO + userId);
        CartVO cartVO = objectMapper.readValue(cartUserId, CartVO.class);
        List<GoodsVO> goodsVOList = cartVO.getGoodsVOList();
        List<GoodsVO> goodsVOList1 = objectMapper.convertValue(goodsVOList, new TypeReference<List<GoodsVO>>() {
            @Override
            public Type getType() {
                return super.getType();
            }
        });
        log.info("goodsVOList1===>{}",goodsVOList1);
        for (Integer goodsId : goodsIds) {
            for (int i = 0; i < goodsVOList1.size(); i++) {

//            for (GoodsVO goodsVO : goodsVOList1) {
//                if (goodsVO.getId()==goodsId){
                    if (goodsVOList1.get(i).getId() == goodsId){
                    boolean remove = goodsVOList1.remove(goodsVOList1.get(i));
                    if (remove){
                        count++;
                    }
                }
            }
        }
        cartVO.setGoodsVOList(goodsVOList1);
        cartVO.setUpdateTime(System.currentTimeMillis());
        String s = objectMapper.writeValueAsString(cartVO);
        redisTemplate.opsForValue().set(CART_INFO+userId,s);
        return count>0?"success!":"fail!";
    }

    @Override
    public String updateCheckedStatus(Integer userId, Integer goodsId, Integer checked) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        Object o = redisTemplate.opsForValue().get(CART_INFO + userId);
        CartVO cartVO = objectMapper.readValue(o.toString(), CartVO.class);
        List<GoodsVO> goodsVOList = cartVO.getGoodsVOList();
        List<GoodsVO> goodsVOList1 = objectMapper.convertValue(goodsVOList, new TypeReference<List<GoodsVO>>() {
            @Override
            public Type getType() {
                return super.getType();
            }
        });
        for (GoodsVO goodsVO : goodsVOList1) {
            if (goodsVO.getId()==goodsId){
                goodsVO.setChecked(checked);
            }
        }
        cartVO.setGoodsVOList(goodsVOList1);
        cartVO.setUpdateTime(System.currentTimeMillis());
        String s = objectMapper.writeValueAsString(cartVO);
        redisTemplate.opsForValue().set(CART_INFO+userId,s);
        return "success!";
    }
}
